﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Net;
using System.Net.Sockets;


public interface IClientsManagerListener
{
    void OnNewClient(Remote remote);
    void OnDisConnect(Remote remote);
}

public class TCPClientsManager : ClientsManagerBase, IGameLifeCycle, ITCPSocketServer
{
    /// <summary>
    /// 在线客户端
    /// </summary>
    //protected List<TCPClient> m_OnlineUsers = new List<TCPClient>();
    //public List<TCPClient> onlineUsers => m_OnlineUsers;

    /// <summary>
    /// 断线客户端
    /// </summary>
    //protected List<TCPClient> m_OfflineUsersList = new List<TCPClient>();

    /// <summary>
    /// 断线等待时间
    /// </summary>
    public  int offlineWaitSceonds = 180;

    //public Action<TCPClient> onUserOffline;

    TCPSocketServer m_TCPSocketServer;

    IEncode m_Encoder;
    IDecode m_Decoder;

    protected override ServerSocket socketServer
    {
        get
        {
            if(m_TCPSocketServer == null)
            {
                m_TCPSocketServer = new TCPSocketServer(this, m_Encoder, m_Decoder);
            }
            return m_TCPSocketServer;
        }
    }

    AtomLock m_AtomLock = new AtomLock();

    public TCPClientsManager()
    {

    }

    public TCPClientsManager(IEncode encoder,IDecode decoder)
    {
        m_Encoder = encoder;
        m_Decoder = decoder;

        m_TCPSocketServer = new TCPSocketServer(this, null, null);
    }

    public override void Start(int port, int maxConnectCount)
    {
        socketServer.Start(port, maxConnectCount);
    }
    
    void ITCPSocketServer.OnNewConnected(EndPoint endPoint, Socket connect)
    {
        TCPSocketServer serverSocket = new TCPSocketServer(connect,m_Encoder,m_Decoder);

        TCPClient newClient = NewClient(GetCurClientId(), serverSocket, OnRemoteDisconnet);

        GameDebug.Log($"用户上线  clientId:{newClient.clientId}  ipEndPoint:{newClient.ipEndPoint}");

        this.AddClient((IPEndPoint)endPoint, newClient);
        
        //AddOnlineUser(newClient);

        this.listener?.OnNewClient(newClient);
        
       // m_AtomLock.DoAction(() =>
       //{
       //    for (int i = 0; i < m_OfflineUsersList.Count;)
       //    {
       //        if (IPEndPointKey.GetIPEndPointKey(m_OfflineUsersList[i].ipEndPoint).Equals(IPEndPointKey.GetIPEndPointKey((IPEndPoint)endPoint)))
       //        {
       //            m_OfflineUsersList.RemoveAt(i);
       //        }
       //        else
       //        {
       //            i++;
       //        }
       //    }
       //});
    }

    protected virtual TCPClient NewClient(long clientId, TCPSocketServer serverSocket, Action<TCPRemote> onDisconnect)
    {
        return new TCPClient(GetCurClientId(), serverSocket, OnRemoteDisconnet);
    }

    public void OnReceiveData(EndPoint endPoint, byte[] data)
    {

    }

    public void OnRecOrSendFailed(EndPoint endPoint)
    {
        GameDebug.LogError($"监听Socket断开连接");
    }
    
    /// <summary>
    /// 有客户端断开连接
    /// </summary>
    /// <param name="rc"></param>
    protected virtual void OnRemoteDisconnet(TCPRemote rc)
    {
        TCPClient client = rc as TCPClient;

        if(rc.userID == 0)
        {
            GameDebug.Log($"rc:{rc.clientId} {rc.ipEndPoint}  尚未登录已断开连接");
        }
        this.RemoveClient(rc.ipEndPoint);

        //m_AtomLock.DoAction(() =>
        //{
        //    if (!m_OfflineUsersList.Contains(client))
        //    {
        //        m_OfflineUsersList.Add(client);
        //    }
        //    GameDebug.Log($"OnRemoteDisconnet offline users:{m_OfflineUsersList.GetListStr()}");
        //});

        //m_OnlineUsers.Remove(client);

        this.listener?.OnDisConnect(client);
    }

    /// <summary>
    /// 添加登录用户
    /// </summary>
    /// <param name="userId"></param>
    /// <param name="_client"></param>
    public override void OnAddLoginedUser(long userId,Remote _client)
    {
        base.OnAddLoginedUser(userId, _client);

        IPEndPointKey key = IPEndPointKey.GetIPEndPointKey(_client.ipEndPoint);

        Remote remote;

        bool exist = m_ClientList.TryGetValue(key, out remote);

        if(exist)
        {
            TCPClient client = remote as TCPClient;

            if (client != null)
            {
                client.userID = userId;

                GameDebug.Log($"用户登入  userId:{client.userID}  clientId:{client.clientId}  ipEndPoint {client.ipEndPoint}");

                //m_AtomLock.DoAction(() =>
                //{
                //    for (int i = 0; i < m_OfflineUsersList.Count;)
                //    {
                //        if (m_OfflineUsersList[i].userID.Equals(userId))
                //        {
                //            m_OfflineUsersList.RemoveAt(i);
                //        }
                //        else
                //        {
                //            i++;
                //        }
                //    }
                //});
            }
            else
            {
                GameDebug.LogError($"client == null  clientId:{remote?.clientId}");
            }
        }
        else
        {
#if DEBUG
            GameDebug.LogError($"did not exist _client.clientId:{_client.clientId} clientList:{m_ClientList.dictionary.GetDictStr()}");
#endif
        }
    }


    ///// <summary>
    ///// 添加上线用户
    ///// </summary>
    ///// <param name="client"></param>
    //protected void AddOnlineUser(TCPClient client)
    //{
    //    GameDebug.Log($"用户上线:{client.ipEndPoint.Address} clientId:{client.clientId}");

    //    //this.m_OnlineUsers.Add(client);

    //    //GameDebug.Log($"online users:{m_OnlineUsers.GetListStr()}");
    //}

    void CheckUserOffline()
    {
        List<Remote> toRemove = new List<Remote>();
        m_ClientList.Foreach((pair) => 
        {
            Remote client = pair.Value;

            long curTime = (long)(DateTime.Now.Ticks / 10000000d);

            if (client.serverSocket == null || !client.serverSocket.connected)
            {
                GameDebug.Log($"移除断线用户：playerId:{client.userID} address:{ client.ipEndPoint}");

                toRemove.Add(pair.Value);
            }
        });

        foreach (var toRemoveClient in toRemove)
        {
            GameDebug.Log($"移除  , address:{ toRemoveClient.ipEndPoint}");
            this.OnRemoteDisconnet(toRemoveClient as TCPRemote);
        }
    }

    long m_LastUpdateSeconds;

    public override void Update(int frameCount)
    {
        //5秒刷新一次
        //long curTime = (long)(DateTime.Now.Ticks / 10000000d);

        //if (curTime - m_LastUpdateSeconds >= 10)
        //{
        //    m_LastUpdateSeconds = curTime;

        //    m_AtomLock.DoAction(CheckUserOffline);


        //    //foreach(Remote user in this.clientList.Values)
        //    //{
        //    //    TCPClient client = user as TCPClient;
        //    //    if (client != null && !client.connected)
        //    //    {
        //    //        this.RemoveClient
        //    //    }
        //    //}
        //}

        foreach (Remote client in this.clientList.Values)
        {
            client.Update();
        }
    }

}

